'''
Copyright: 
Descripttion: 
version: 
Author: chengx
Date: 2021-11-24 16:22:29
LastEditors: chengx
LastEditTime: 2022-03-07 22:01:01
'''
import cv2
import os
import numpy as np
import matplotlib.pyplot as plt
from skimage import data,filters

# 通过阈值分割
def image_cut(img_path,min_area,max_area):

    """
    Parameters: img_path:预览bmp图片路径
                threshold：阈值
                min_area：最小面积
                max_area：最大面积
    Description: 二值化分割图中特征，获取各特征的中心坐标及特征数量
    Returns:返回分割区域数量，外接矩形最大边长，分割区域中心点坐标,获取坐标的顺序是从图片下方往上
    """
    #读图
    bmp_img = cv2.imdecode(np.fromfile(img_path, dtype=np.uint8), 0) 
    bmp_img2 = cv2.imdecode(np.fromfile(img_path, dtype=np.uint8),1)
    print(bmp_img.shape)
    bmp_img = trans(bmp_img)
    bmp_img2 = trans(bmp_img2)

    cv2.imwrite('0.bmp',bmp_img2)

    T = filters.threshold_otsu(bmp_img)
    # print ('T',T)
    _, thresh  = cv2.threshold(bmp_img,T, 255, cv2.THRESH_BINARY)

    cv2.imshow('thresh', thresh)
    cv2.imwrite('1.bmp',thresh)


    #查找轮廓
    contours,_ = cv2.findContours(thresh , cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
    print(len(contours))
    for c in contours:
        area = cv2.contourArea(c)#轮廓面积
        # 在bmp图像上画出轮廓，-1表示绘出全部轮廓，如果传入的轮廓不是列表，则用1是无效的，最后一位表示线宽
        if area >min_area and area<max_area:
            cv2.drawContours(bmp_img2, c, -1, (0,0,255), 2)#绘制轮廓

    cv2.imshow("contours2",bmp_img2)
    cv2.imwrite('2.bmp',bmp_img2)
    cv2.waitKey()

def trans(bmp_img):#旋转90度
    #旋转90°
    trans_img = cv2.transpose(bmp_img)
    new_img = cv2.flip(trans_img, 1)
    bmp_img=new_img
    return bmp_img

def watershed(): # 做胶囊的
    '''
    完成分水岭算法步骤：
    1、加载原始图像
    2、阈值分割，将图像分割为黑白两个部分
    3、对图像进行开运算，即先腐蚀在膨胀
    4、对开运算的结果再进行膨胀，得到大部分是背景的区域
    5、通过距离变换 Distance Transform 获取前景区域
    6、背景区域sure_bg 和前景区域sure_fg相减，得到即有前景又有背景的重合区域
    7、连通区域处理
    8、最后划分
    '''
    img_path = './cap2.bmp'
    img = cv2.imdecode(np.fromfile(img_path, dtype=np.uint8), 0)
    # 旋转90度
    img = trans(img)
    # otsu获取阈值
    T = filters.threshold_otsu(img)
    # print ('T',T)

    _, thresh  = cv2.threshold(img,T, 255, cv2.THRESH_BINARY)
    for i in range(thresh.shape[0]):
        for j in range(thresh.shape[1]):
            if thresh[i,j] == 0:
                thresh[i,j]=255
            else:
                thresh[i,j]=0

    # cv2.imshow('thresh', thresh)
    
    # 开运算去噪
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
    opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 3)
    # cv2.imshow()

    # 膨胀后确保背景
    sure_bg = cv2.dilate(opening,kernel,iterations=2)

    dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
    cv2.normalize(dist_transform, dist_transform, 0, 1.0, cv2.NORM_MINMAX)
    # cv2.imshow('dist_transform', dist_transform)
    # 寻找确定的前景
    ret, sure_fg = cv2.threshold(dist_transform, 0.7*dist_transform.max(), 255, 0)
    sure_fg = np.uint8(sure_fg)
    unknown = cv2.subtract(sure_bg,sure_fg)
    # cv2.imshow('sure_bg', sure_bg)
    # cv2.imshow('sure_fg', sure_fg)
    # 通过膨胀减腐蚀查找未知区域
    # cv2.imshow('unknown area', unknown)#就只有0和255两种点

    # 求取连通域
    ret, markers1 = cv2.connectedComponents(sure_fg)
    # 0不确定区域，1为背景，大于1的为前景
    markers = markers1+1
    markers[unknown==255] = 0

    img2 = cv2.imdecode(np.fromfile(img_path, dtype=np.uint8), 1)
    # 旋转90度
    img2 = trans(img2)

    markers3 = cv2.watershed(img2,markers)
    img2[markers3 == -1] = [0,0,255]
    cv2.imshow("img",img2)


    #保存分割好的二值化图。
    markers3 = np.where(markers3 >1,255,0)
    markers3 = markers3.astype(np.uint8)

    #查找轮廓
    contours,_ = cv2.findContours(markers3 , cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
    # print(len(contours))
    for c in contours:
        # 在bmp图像上画出轮廓，-1表示绘出全部轮廓，如果传入的轮廓不是列表，则用1是无效的，最后一位表示线宽
        cv2.drawContours(img2, c, -1, (0,0,255), 1)#绘制轮廓

    # cv2.imshow("img222",img2)
    # cv2.imwrite('4.bmp',img2)
    cv2.imshow('cut',markers3)
    cv2.waitKey(0)


if __name__ == '__main__':
    # imagePath = './cap2.bmp'# chinese4  # tablet # cap2.bmp
    # image_cut(imagePath,80,50000)
    watershed()